#include <iostream>
#include "Util.h"
#include <string>

using namespace std;

Util* Util::instant;

Util::Util()
{
	this->instant = NULL;
}

Util::~Util()
{
}


Util* Util::getInstant()
{
	if ( instant == NULL )
		instant = new Util();
	return instant;
}

//Check exist file?
int Util::isExist(char* filename)
{
	FILE* file = fopen(filename, "r");
	if(file)
	{
		fclose(file);
		return 1;
	}
	return 0;
}

//cut space before of string
char* Util::cutSpaceBefore ( char * str )
{
	//copy
	char* temp_str = new char[ strlen ( str )];
	strcpy ( temp_str, str );

	while ( temp_str[0] == ' ' )
	{
		for (int i = 0; i < strlen( temp_str ) - 1; i++)
			temp_str[i] = temp_str[i + 1];
		temp_str[strlen( temp_str ) - 1] = '\0';
	}
	return temp_str;
}

//convert char ABCDF to number
int Util::switchCharToNumver ( char ch )
{
	switch (ch)
	{
	case 'A':
	case 'a':
		return 10;
	case 'B':
	case 'b':
		return 11;
	case 'C':
	case 'c':
		return 12;
	case 'D':
	case 'd':
		return 13;
	case 'E':
	case 'e':
		return 14;
	case 'F':
	case 'f':
		return 15;
	default:
		return (ch - '0');
	}
}

//Ox1006 -> 6 not use 0x1 only conver 006
int Util::convertHexToDec (char* hec )
{
	int a2, a1, a0;
	a2 = switchCharToNumver ( hec[3] );
	a1 = switchCharToNumver ( hec[4] );
	a0 = switchCharToNumver ( hec[5] );
	
	return ( a2*16*16 + a1*16 + a0 );
}

//replace a char in str
char* Util::replaceChar ( char* str, char ch, char ch_replace )
{
	char* str_re = new char[ strlen ( str ) ];
	strcpy ( str_re, str );
	for ( int i = 0; i < strlen ( str_re ); i++ )
				if ( str_re[i] == ch )	
			str_re[i] = ch_replace;	
	return str_re;
}

//convert Dec to char
char* Util::convertDecToChar ( int num )
{
	if ( num == 0 )
		return "0";
	int n = num;
	int count = 0;
	int _array[20];
	while ( n != 0 )
	{
		_array[count] = n % 10;
		n /= 10;
		count++;
	}
	
	char* str = new char[count];
	for ( int i = count - 1; i >= 0; i-- )
		str[count - i - 1] = _array[i] + '0';
	str[count] = '\0';
	return str;
}

int Util::stringContainString ( char* str, char* subStr )
{
	string _str ( str );
	string _subStr ( subStr );

	return ( ( _str.find( _subStr ) != string::npos) ); 
}

char* Util::keepNumberInString ( char* str )
{
	char* keepNum = new char[ strlen( str )];
	strcpy( keepNum, str );
	for ( int i = 0; i < strlen( keepNum ); i++ )
	{
		if ( !( keepNum[i] == '-' || ( keepNum[i] >= '0' && keepNum[i] <= '9' ) ) )
			keepNum[i] = ' ';
	}
	return keepNum;
}

//get image name of sprite
char* Util::getImageNameWithExtent ( char* spriteName )
{
	char lineOrigin[200], _temp[200], tempImageName[255], imageName[50];	
	char *line;

	FILE *fIn = fopen( spriteName, "r");
	if ( fIn == NULL )
	{
		cout << endl << "\nCan not read file: " << spriteName;
		return "";
	}

	while ( !feof ( fIn ) )
	{		
		fgets( lineOrigin, sizeof( lineOrigin ),fIn );
		line = Util::getInstant()->cutSpaceBefore ( lineOrigin );
				
		if ( line[0] == 'I' && line[1] == 'M' && line[2] == 'A' && line[3] == 'G' && line[4] == 'E' )
		{		
			int w, h;
			sscanf(&line[0], "%s" "%s" "%s" "%s" "%s" "%s" "%s" "%s" "%d" "%s" "%d", &_temp, &_temp, &tempImageName, &_temp, &_temp, &_temp, &_temp, &_temp, &w, &_temp, &h);
			
			//tempImageName with ".../imageName.png"
			//cut "" 

			char temp[50]; 
			for (int i = strlen ( tempImageName ) - 2; i >= 0; i-- )
			{	
				if ( tempImageName[i] == '\\' )
				{
					temp[strlen ( tempImageName ) - 2 - i] = '\0';
					break;
				}
				temp[strlen ( tempImageName ) - 2 - i] = tempImageName[i];
			}

			for (int i = strlen ( temp ) - 1; i >= 0; i-- )
			{	
				
				imageName[strlen ( temp ) - 1 - i] = temp[i];
			}

			//cut .png
			imageName[strlen ( temp )] = '\0';			
			break;
		}

		memset ( lineOrigin, 0, sizeof ( lineOrigin ) );
		memset ( line, 0, sizeof ( line ) );
	}

	fclose ( fIn );

	char* name = new char[strlen (imageName)];
	strcpy (name, imageName);
	return name;
}

//get image name of sprite with non extend ex menu
char* Util::getImageName( char* spriteName )
{
	char* temp = getImageNameWithExtent ( spriteName );
	int lengh = strlen ( temp ) - strlen ( ".png" );
	char* name = new char [lengh];
	strcpy ( name, temp );
	name[lengh] = '\0';	
	return name;
}

//get size of image
Point Util::getImageSize ( char* spriteName )
{
	Point imageSize;
	char lineOrigin[200], temp[200];
	char *line;

	FILE *fIn = fopen( spriteName, "r");
	if ( fIn == NULL )
	{
		cout << endl << "\nCan not read file: " << spriteName;		
		return imageSize;
	}

	while ( !feof ( fIn ) )
	{		
		fgets( lineOrigin, sizeof( lineOrigin ),fIn );
		line = Util::getInstant()->cutSpaceBefore ( lineOrigin );
				
		if ( line[0] == 'I' && line[1] == 'M' && line[2] == 'A' && line[3] == 'G' && line[4] == 'E' )
		{		
			int w, h;
			sscanf(&line[0], "%s" "%s" "%s" "%s" "%s" "%s" "%s" "%s" "%d" "%s" "%d", &temp, &temp, &temp, &temp, &temp, &temp, &temp, &temp, &imageSize.x, &temp, &imageSize.y);
			break;
		}

		memset ( lineOrigin, 0, sizeof ( lineOrigin ) );
		memset ( line, 0, sizeof ( line ) );
		memset ( temp, 0, sizeof ( temp ) );
	}

	fclose ( fIn );

	return imageSize;
}

//get max module can
int Util::getModuleMax ( char* spriteName )
{
	char lineOrigin[200], temp[20], tempHex[10];
	char* line;
	int maxNum = -1, tempNum;

	
	FILE *fIn = fopen( spriteName, "r");
	if ( fIn == NULL )
	{
		cout << endl << "\nCan not read file: " << spriteName;		
		return -1;
	}

	while ( !feof ( fIn ) )
	{		
		fgets( lineOrigin, sizeof( lineOrigin ),fIn );
		line = Util::getInstant()->cutSpaceBefore ( lineOrigin );

		if ( line[0] == 'M' && line[1] == 'D' )
		{
			sscanf(&line[0], "%s" "%s", &temp, &tempHex );
			tempNum = Util::getInstant()->convertHexToDec ( tempHex );
			if ( maxNum < tempNum )
				maxNum = tempNum;
		}

		if ( line[0] == '}' )
			break;

		memset ( lineOrigin, 0, sizeof ( lineOrigin ) );
		memset ( line, 0, sizeof ( line ) );
		memset ( temp, 0, sizeof ( temp ) );
		memset ( temp, 0, sizeof ( tempHex ) );
	}

	fclose (fIn);	
	return ( maxNum + 1 );
}

//get max frame can // return -1 if not exist
int Util::getFrameMax ( char* spriteName )
{
	char lineOrigin[200], temp[20], tempHex[10];
	char* line;
	int maxNum = -1, tempNum;

	
	FILE *fIn = fopen( spriteName, "r");
	if ( fIn == NULL )
	{
		cout << endl << "\nCan not read file: " << spriteName;		
		return -1;
	}

	while ( !feof ( fIn ) )
	{		
		fgets( lineOrigin, sizeof( lineOrigin ),fIn );
		line = Util::getInstant()->cutSpaceBefore ( lineOrigin );

		if ( line[0] == '0' && line[1] == 'x' && line[2] == '2' )
		{
			sscanf(&line[0], "%s", &tempHex );
			tempNum = Util::getInstant()->convertHexToDec ( tempHex );
			if ( maxNum < tempNum )
				maxNum = tempNum;
		}

		if ( line[0] == '0' && line[1] == 'x' && line[2] == '3' ) //anim
			break;

		memset ( lineOrigin, 0, sizeof ( lineOrigin ) );
		memset ( line, 0, sizeof ( line ) );
		memset ( temp, 0, sizeof ( tempHex ) );
	}

	fclose (fIn);	
	return ( maxNum + 1 );
}

//get max anim can // return -1 if not exist
int Util::getAnimMax ( char* spriteName )
{
	char lineOrigin[200], temp[20], tempHex[10];
	char* line;
	int maxNum = -1, tempNum;

	
	FILE *fIn = fopen( spriteName, "r");
	if ( fIn == NULL )
	{
		cout << endl << "\nCan not read file: " << spriteName;		
		return -1;
	}

	while ( !feof ( fIn ) )
	{		
		fgets( lineOrigin, sizeof( lineOrigin ),fIn );
		line = Util::getInstant()->cutSpaceBefore ( lineOrigin );

		if ( line[0] == '0' && line[1] == 'x' && line[2] == '3' )
		{
			sscanf(&line[0], "%s", &tempHex );
			tempNum = Util::getInstant()->convertHexToDec ( tempHex );
			if ( maxNum < tempNum )
				maxNum = tempNum;
		}
		
		memset ( lineOrigin, 0, sizeof ( lineOrigin ) );
		memset ( line, 0, sizeof ( line ) );
		memset ( temp, 0, sizeof ( tempHex ) );
	}

	fclose (fIn);	
	return ( maxNum + 1 );
}

char* Util::getGtsFile ( char* guiName )
{
	char lineOrigin[200], temp[20];
	char* gtsFile;
	char* line;	

	
	FILE *fIn = fopen( guiName, "r");
	if ( fIn == NULL )
	{
		cout << endl << "\nCan not read file: " << guiName;		
		return NULL;
	}

	while ( !feof ( fIn ) )
	{				
		fgets( lineOrigin, sizeof( lineOrigin ),fIn );
		line = Util::getInstant()->cutSpaceBefore ( lineOrigin );

		if ( line[0] == 'L' && line[1] == 'O' && line[2] == 'A' && line[3] == 'D'  && line[4] == '_'  && line[5] == 'T'  && line[6] == 'E' && line[7] == 'M' && line[8] == 'P' )
		{		
			char tempGts[50];
			sscanf ( &line[0], "%s" "%s", &temp, &tempGts );
			//".\gui.gts" cut to get gui.gts
			int i;
			for ( i = 0; i < strlen ( tempGts ) - 4; i ++ )
				tempGts[i] = tempGts[i + 3];
			tempGts[i] = '\0';
			gtsFile = new char[strlen( tempGts )];
			strcpy( gtsFile, tempGts );
			break;
		}
		
		memset ( lineOrigin, 0, sizeof ( lineOrigin ) );
		memset ( line, 0, sizeof ( line ) );		
	}

	fclose (fIn);	
	
	return gtsFile;
}

char* Util::getSpriteListFile ( char* gtsFile )
{
	char line[200], temp[20];
	char* spritListFile;
		
	FILE* f = fopen ( gtsFile, "r" );
	if ( f == NULL )
	{
		cout << "Can not read file: " << gtsFile << endl;
		return NULL;
	}

	while ( !feof ( f ) )
	{				
		fgets( line, sizeof( line ), f );	

		if ( stringContainString ( line, "DATA_TYPE SPRITE_LIST \"Sprites\"" ) )
		{		
			fgets( line, sizeof( line ), f );
			memset ( line, 0, sizeof ( line ) );		
			fgets( line, sizeof( line ), f );	
			char tempSpriteListFile[50];
			sscanf ( &line[0], "%s" "%s", &temp, &tempSpriteListFile );
			//".\gui.gts" cut to get gui.gts
			int i;
			for ( i = 0; i < strlen ( tempSpriteListFile ) - 1; i ++ )
				tempSpriteListFile[i] = tempSpriteListFile[i + 1];
			tempSpriteListFile[i-1] = '\0';
			spritListFile = new char[strlen( tempSpriteListFile )];
			strcpy( spritListFile, tempSpriteListFile );
			break;
		}		
		
		memset ( line, 0, sizeof ( line ) );		
	}

	fclose (f);	
	
	return spritListFile;

}

vector <char* > Util::getLevelFileName ( char* guiName )
{
	char lineOrigin[200], temp[20];
	char* gtsFile;
	char* line;	
	vector< char* > levelArray;

	
	FILE *fIn = fopen( guiName, "r");
	if ( fIn == NULL )
	{
		cout << endl << "\nCan not read file: " << guiName;		
		return levelArray;
	}

	while ( !feof ( fIn ) )
	{	
		
		fgets( lineOrigin, sizeof( lineOrigin ),fIn );
		line = Util::getInstant()->cutSpaceBefore ( lineOrigin );

		if ( line[0] == 'L' && line[1] == 'O' && line[2] == 'A' && line[3] == 'D'  && line[4] == '_'  && line[5] == 'L'  && line[6] == 'E' && line[7] == 'V' && line[8] == 'E' && line[9] == 'L'  )
		{		
			char templevelName[100];
			char* levelName;
			sscanf ( &line[0], "%s" "%s", &temp, &templevelName );
			//LOAD_LEVEL ".\Levels\NEW_GUI.level" cut to get Levels\NEW_GUI.level"
			int i;
			for ( i = 0; i < strlen ( templevelName ) - 4; i ++ )
				templevelName[i] = templevelName[i + 3];
			templevelName[i] = '\0';
			levelName = new char[strlen( templevelName )];
			strcpy( levelName, templevelName );
			levelArray.push_back( levelName );			
		}
		
		memset ( lineOrigin, 0, sizeof ( lineOrigin ) );
		memset ( line, 0, sizeof ( line ) );		
	}

	fclose (fIn);	
	
	return levelArray;
}

int Util::getTemplateID ( char* gtsFile, char* _template )
{
	int countID = -1;
	char line[200], temp[100], tempString[100];
	FILE* f = fopen ( gtsFile, "r" );

	while ( !feof ( f ) )
	{
		fgets( line, sizeof ( line ), f );
		if ( line[0] == 'T' && line[1] == 'E' && line[2] == 'M' && line[3] == 'P' && line[4] == 'L' && line[5] == 'A' && line[6] == 'T' && line[7] == 'E')
		{
			countID++;
			sscanf ( &line[1], "%s" "%s" "%s", &temp, &temp, &tempString );
			//cut ""
			for (int i = 0; i < strlen ( tempString ) - 2; i++ )
				tempString[i] = tempString[i + 1];
			tempString[strlen ( tempString ) - 2] = '\0';
			if ( strcmp (tempString, _template) == 0 )
			{
				fclose ( f );
				return countID;	
			}
		
		}

		memset ( line, 0, sizeof ( line ) );
		memset ( line, 0, sizeof ( tempString ) );
	}

	fclose ( f );
	return -1;
}

int Util::getTemplateMax ( char* gtsFile )
{
	int countID = 0;
	char line[200];
	FILE* f = fopen ( gtsFile, "r" );
	while ( !feof ( f ) )
	{
		fgets( line, sizeof ( line ), f );
		if ( line[0] == 'T' && line[1] == 'E' && line[2] == 'M' && line[3] == 'P' && line[4] == 'L' && line[5] == 'A' && line[6] == 'T' && line[7] == 'E')
			countID++;		
		memset ( line, 0, sizeof ( line ) );		
	}
	 fclose ( f );	
	return countID;
}

int Util::getGuiLevelMax ( char* guiName )
{
	vector< char* > levelArray = getLevelFileName ( guiName );
	int levelCount = levelArray.end() - levelArray.begin();
	return levelCount;
}